package com.irdstudio.devops.agent.plugin.deploy;

import com.irdstudio.bfp.executor.core.plugin.AbstractPlugin;
import com.irdstudio.bfp.executor.core.tinycore.jdbc.dbcp.TConnPool;
import com.irdstudio.devops.agent.dao.SysDeployInfo;
import com.irdstudio.devops.agent.dao.SysDeployInfoDao;
import com.irdstudio.sdk.beans.ssh.utils.RemoteShellClient;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class SSHPlugin extends AbstractPlugin {

    private static final String systemTmpDir = System.getProperty("java.io.tmpdir");


    private PluginSSHConf pluginParam = null;
    private String taskName = null;
    private String pluginName = null;
    private SysDeployInfoDao sysDeployInfoDao =null ;
    private SysDeployInfo sysDeployInfo = null;

    @Override
    protected boolean doReadConfigureFromDB(Connection conn, String szConfIdentify) throws SQLException {

        pluginName = context.getSzPluginName();
        taskName = context.getSzTaskName();

        pluginParam = context.getSzPluginParam(PluginSSHConf.class);

        if (pluginParam ==null)
        {
            context.setSzLastErrorMsg("未读取到配置标识为：" + szConfIdentify + "的数据MySQL配置!");
            return false;
        }else {
            if(!pluginParam.getAppId().isEmpty()){
                sysDeployInfoDao  = new SysDeployInfoDao(conn);
                sysDeployInfo = sysDeployInfoDao.queryByAppIdAndAppPort(pluginParam.getAppId(),pluginParam.getTomcatPort());
                if (sysDeployInfo!=null){
                    sysDeployInfo.setAppState("D");
                    sysDeployInfoDao.updateByPk(sysDeployInfo);
                    sysDeployInfo.setAppState("R");
                }
                else {
                    sysDeployInfo =  sysDeployInfoDao.insertSysDeployInfo(pluginParam,context.getSzSubsCode());
                    sysDeployInfo.setAppState("R");
                }
            }
            return true;
        }
    }

    @Override
    public boolean execute() throws Exception {
        logger.info("调用Tomcat应用部署插件，部署应用:"+taskName);

        // 复制 agent脚本与tomcat 到临时目录 agent
        copyAgentToTmp();
        // 2.针对每台服务器发布应用
        logger.info("开始部署应用:"+taskName+" 到服务器:"+pluginParam.getServerIp()+" 端口:"+pluginParam.getTomcatPort());
        // 远程操作Linux服务器
        RemoteShellClient rsc = new RemoteShellClient(pluginParam.getServerIp(),
                pluginParam.getServerUserName(), pluginParam.getServerPwd());
        boolean loginFlag = rsc.login();
        if (!loginFlag) {
            logger.info("登陆服务器失败");
            return loginFlag;
        }
        // 如果不存在该目录则进行创建并初始化
        String localAgentPath = systemTmpDir + File.separator + "agent" + File.separator;
        if (!rsc.getFileProperties("/agent")) {
            // 2.1.创建目录
            rsc.exec("mkdir /agent");
            logger.info("执行命令:mkdir /agent 创建目录");
            // 2.2.上传tomcat包到agent目录
            rsc.putFile(localAgentPath + "apache-tomcat-8.5.59.tar.gz", "/agent");
            logger.info("上传文件:"+localAgentPath + "apache-tomcat-8.5.59.tar.gz 到 /agent");
            // 2.3.上传agent所需要的sh到服务器
            rsc.putFile(localAgentPath + "startTomcatApp.sh", "/agent");
            logger.info("上传文件:"+localAgentPath + "startTomcatApp.sh 到 /agent");

            // 2.4.解压tomcat
            // rsc.exec("gzip -d d://apptemplate//agent//apache-tomcat-8.5.59.tar.gz");
            // 2.5.更改sh脚本的权限
            rsc.exec("chmod 777 /agent/startTomcatApp.sh");
            logger.info("执行命令:chmod 777 /agent/startTomcatApp.sh");
        }

        // 如果存在agent,则直接上传应用包并启动应用
        String localProjectWar = pluginParam.getAppArtifactLocation();
        logger.info("本地war包路径:"+localProjectWar);
        rsc.login();
        rsc.putFile(localProjectWar, "/agent");
        logger.info("执行命令 " + "/agent/startTomcatApp.sh " + pluginParam.getAppName() + " " + pluginParam.getTomcatPort());
        int status = rsc.exec("/agent/startTomcatApp.sh " + pluginParam.getAppName() + " " + pluginParam.getTomcatPort());
        if (status == -1) {
            logger.info("执行发布命令 /agent/startTomcatApp.sh 状态 {}", status);
            return false;
        }
        Connection conn = TConnPool.getDefaultPool().getConnection();
        sysDeployInfoDao = new SysDeployInfoDao(conn);
        sysDeployInfoDao.updateByPk(sysDeployInfo);
        rsc.exit();
        return true;
    }

    private void copyAgentToTmp() {
        File tmpAgent = new File(systemTmpDir, "agent");
        if (!tmpAgent.exists()) {
            tmpAgent.mkdir();
            String root = "/agent";
            List<String> fileList = getResourceFiles(root);
            if (CollectionUtils.isNotEmpty(fileList)) {
                for (String file : fileList) {
                    try {
                        InputStream in = getResourceAsStream(root + "/" + file);
                        if (in != null) {
                            FileUtils.copyInputStreamToFile(in, new File(tmpAgent, file));
                        }
                    } catch (IOException e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        }
    }

    private List<String> getResourceFiles(String path)  {
        List<String> filenames = new ArrayList<>();
        InputStream in;
        BufferedReader br;
        try {
            in = getResourceAsStream(path);
            br = new BufferedReader(new InputStreamReader(in));
            String resource;

            while ((resource = br.readLine()) != null) {
                filenames.add(resource);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return filenames;
    }

    private InputStream getResourceAsStream(String resource) {
        final InputStream in
                = getContextClassLoader().getResourceAsStream(resource);

        return in == null ? getClass().getResourceAsStream(resource) : in;
    }

    private ClassLoader getContextClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
}
